'use strict';

const util = require('util');
const when = require('when');
const keys = require('when/keys');
const request = require('request');
const URL = require('url');
const createError = require('http-errors');

const slice = Array.prototype.slice;
const logFactory = require('../factories/logFactory');
const log = logFactory.get("request");
const configuration = require('../factories/configuration');
const config = configuration.get('server');

const TOKEN_NAME = config.token.name;
const TOKEN_KEY = config.token.key;

//请求接口相关配置
const cfg = config.req;
const api = cfg.api;

const METHODS = ['get', 'head', 'post', 'put', 'patch', 'del'];

/*
 * @param url [string | object] 请求地址(必填)
 * @param options [object] 请求参数，第一个参数为对象时可以不传(选填)
 */
function Http(url, options) {
    var deferred = when.defer();
    //兼容object传参
    if (typeof url === 'object') {
        options = url;
        url = options.url;
    }
    //非http开头的url，自动拼接配置的rest地址
    url = !url.indexOf('http') ? url : api + url;
    //配置gzip压缩
    options.gzip = options.gzip || cfg.gzip
        //默认get方法
    options.method = options.method || 'GET';
    let headers = options.headers || {};
    if (options.req) {
        let _headers = options.req.headers;
        Object.assign(headers, {
            'x-forwarded-for': _headers['x-forwarded-for'] || _headers['x-real-ip'] || _headers.remoteip || (options.req.connection || {}).remoteAddress || (options.req.socket || {}).remoteAddress || (options.req.connection.socket || {}).remoteAddress,
            'user-agent': _headers['user-agent'],
            cookie: 'LKEY="' + options.req.cookies.LKEY + '"'
        });
        if (options.token !== false) {
            let token = options.req.cookies[TOKEN_NAME] || options.req[TOKEN_KEY];
            if (token) {
                headers[TOKEN_KEY] = token;
            }
        }
        delete options.req;
    }
    //保持跟目标host一致
    headers.host = URL.parse(url).host;
    options.headers = headers;

    log.info('请求转发开始：【' + url + '】', JSON.stringify(options));
    request(url, options, function(error, response, body) {
        var statusCode = response && response.statusCode || 500;
        if (error) {
            log.error('网络请求异常：【' + url + '】', error);
            let httpError = createError(statusCode, error);
            deferred.reject(httpError);
            return;
        }
        if (body) {
            if (~response.headers['Content-Type'].indexOf('application/json')) {
                if (typeof body === 'string') {
                    try {
                        body = JSON.parse(body)
                    } catch (e) {
                        log.error('响应数据非json格式：【' + url + '】', body);
                        let httpError = createError(500, body);
                        deferred.reject(httpError);
                        return;
                    }
                }
            } else {
                log.warn('响应数据非json格式：【' + url + '】', body);
            }
        }
        if (statusCode == 200) {
            deferred.resolve({
                data: body,
                res: response
            });
            log.info('请求转发成功：【' + url + '】', JSON.stringify(body));
        } else {
            let httpError = createError(statusCode, '服务器打盹了');
            deferred.reject(httpError);
            log.error('请求返回异常：【' + url + '】', body);
        }
    });
    return deferred.promise;
};

function MultiHttp(options, cb) {
    if (util.isArray(options)) {
        return when.map(options, cb || _request);
    }
    if (util.isObject(options)) {
        return keys.map(options, cb || _request);
    }
};

const ajax = {
    config: cfg,
    request: _request,
    map: {
        /*
         * @param options [object] 请求参数(必填)
         */
        request(options) {
            if (arguments.length > 1) {
                options = slice.call(arguments, 0);
            }
            return _mRequest(options);
        }
    }
};

METHODS.forEach(function(verb) {
    var method = verb === 'del' ? 'DELETE' : verb.toUpperCase();
    ajax[verb] = function(url, options) {
        if (typeof url === 'object') {
            options = url;
            url = options.url;
        }
        options = options || {};
        options.method || (options.method = method);
        return _request(url, options);
    };
    ajax.map[verb] = function(options) {
        if (arguments.length > 1) {
            options = slice.call(arguments, 0);
        }
        return _mRequest(options, ajax[verb]);
    };
});

const proxyLog = logFactory.get("proxy");
ajax.proxy = function(req, options) {
    var url = req.url;
    url = req.url = url.indexOf('http') === 0 ? url : api + url;
    var method = req.method;
    var _options = {
        method: method,
        headers: req.headers
    };
    var contentType = _options.headers['content-type'] || '';
    switch (method.toUpperCase()) {
        case 'POST':
            if (~contentType.indexOf('application/json')) {
                _options.body = JSON.stringify(req.body);
            } else {
                _options.form = req.body;
            }
            break;
        case 'GET':
            url.indexOf('?') === -1 && (_options.qs = req.query);
            break;
    }
    _options = extend(_options, options);
    proxyLog.info('请求转发开始：【' + url + '】', _options);
    return request(url, _options);
};

module.exports = ajax;